﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;

namespace smp.QueryDb
{
    internal class RawResult : IRawResult
    {
        private List<IRawResultItem> _data = new List<IRawResultItem>();

        internal RawResult(IEnumerable<string> fields)
        {
            Fields = fields;
        }

        internal RawResult(IEnumerable<string> fields, int totalCount)
        {
            Fields = fields;
            TotalRecords = totalCount;
        }

        #region Implementation of IEnumerable

        public IEnumerator<IRawResultItem> GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        #region Implementation of IRawResult

        public IRawResultItem this[int index] { get { return _data[index]; } }

        public int Count { get { return _data.Count; } }

        public int TotalRecords { get; internal set; }

        public bool Contains(IRawResult item)
        {
            return _data.Find(x => x.Equals(item)) != null;
        }

        public IEnumerable<string> Fields { get; private set; }

        public void Add(IDataRecord record)
        {
            _data.Add(new RawResultItem(record, Fields));
        }

        #endregion
    }

    internal class RawResultItem : IRawResultItem
    {
        private Dictionary<string, object> _data = new Dictionary<string, object>();

        internal RawResultItem(IDataRecord record, IEnumerable<string> columns)
        {
            foreach (var column in columns)
            {
                if (_data.ContainsKey(column))
                    throw Helper.Error("Invalid IToRaw call, contains duplication of column name : {0}", column);
                _data.Add(column, record[column]);
            }
        }

        #region Implementation of IRawResultItem

        public bool Equals(IRawResultItem item)
        {
            foreach (var field in _data)
            {
                object itemFieldValue;
                try
                {
                    itemFieldValue = item.Value(field.Key);
                }
                catch (Exception)
                {
                    return false;
                }

                if (itemFieldValue.ToString() != field.Value.ToString())
                    return false;
            }
            return true;
        }

        public object Value(string fieldName)
        {
            if (!_data.ContainsKey(fieldName))
                throw Helper.LogException(new ArgumentException("Invalid field, no data loaded for fieldName " + fieldName));
            return _data[fieldName];
        }

        #endregion
    }
}
